﻿using AutoMapper;
using Microsoft.EntityFrameworkCore;
using TrackSystem.Contracts;
using TrackSystem.Entities.Dtos.Logic;
using TrackSystem.Entities.Dtos.Loop;
using TrackSystem.Entities.Models;
using TrackSystem.Entities.RequestFeatures;
using TrackSystem.EntityFramework.Repositories.Extensions;

namespace TrackSystem.EntityFramework.Repositories
{
    public class LoopRepository : Repositories<LoopTable, int>, ILoopRepository
    {
        private readonly IMapper mapper;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="_dbSet">数据集</param>
        /// <param name="mapper">映射接口</param>
        public LoopRepository(TkDBContent _dbSet, IMapper mapper) : base(_dbSet)
        {
            this.mapper = mapper;
        }

        /// <summary>
        /// 分页获取控制回路
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public PagedList<LoopTable> GetPagedLoops(RequestParameter parameter)
        {
            return Table.OrderByQuery(parameter.QueryString)
                .OrderBy(a => a.Id)
                .Include(a => a.Equip)
                .ToPagedList(parameter.PageNumber, parameter.PageSize);
        }

        public async Task<LoopDto> GetSingle(int id)
        {
            var entity = await _dbContext.Loop.SingleAsync(x => x.Id == id);
            return mapper.Map<LoopDto>(entity);
        }

        /// <summary>
        /// 插入控制回路
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        public async Task<ApiResult<LoopDto>> InsertLoopAsync(LoopTable table)
        {
            try
            {
                var counter = await CountAsync(a => a.Name == table.Name);
                if (counter > 0)
                {
                    return ApiResult<LoopDto>.Fail($"存在同名的控制回路(Name: {table.Name})");
                }

                counter = await _dbContext.Equip.CountAsync(a => a.Id == table.equipId);
                if (counter == 0)
                {
                    return ApiResult<LoopDto>.Fail("控制回路所属设备不存在");
                }

                var pv = await _dbContext.Vars.FirstOrDefaultAsync(a => a.Name == table.PVName);
                if (pv == null)
                {
                    return ApiResult<LoopDto>.Fail($"过程值变量不存在(PVName: {table.PVName})");
                }
                if (pv.DataType == Entities.Extensions.DataTypeEnum.BOOLEAN || 
                    pv.DataType == Entities.Extensions.DataTypeEnum.STRING)
                {
                    return ApiResult<LoopDto>.Fail($"过程值变量类型不正确(PVName: {table.PVName})");
                }

                var sv = await _dbContext.Vars.FirstOrDefaultAsync(a => a.Name == table.SVName);
                if (sv == null)
                {
                    return ApiResult<LoopDto>.Fail($"设定值变量不存在(SVName: {table.SVName})");
                }
                if (sv.DataType == Entities.Extensions.DataTypeEnum.BOOLEAN || 
                    sv.DataType == Entities.Extensions.DataTypeEnum.STRING)
                {
                    return ApiResult<LoopDto>.Fail($"设定值变量类型不正确(SVName: {table.SVName})");
                }
                if (sv.ReadOnly)
                {
                    return ApiResult<LoopDto>.Fail($"设定值变量是只读的(SVName: {table.SVName})");
                }

                var op = await _dbContext.Vars.FirstOrDefaultAsync(a => a.Name == table.OPName);
                if (op == null)
                {
                    return ApiResult<LoopDto>.Fail($"输出值变量不存在(OPName: {table.OPName})");
                }
                if (op.DataType == Entities.Extensions.DataTypeEnum.BOOLEAN || 
                    op.DataType == Entities.Extensions.DataTypeEnum.STRING)
                {
                    return ApiResult<LoopDto>.Fail($"输出值变量类型不正确(OPName: {table.OPName})");
                }
                if (op.ReadOnly)
                {
                    return ApiResult<LoopDto>.Fail($"输出值变量是只读的(OPName: {table.OPName})");
                }                

                var entity = await InsertAsync(table);
                if (entity == null)
                {
                    return ApiResult<LoopDto>.Fail("添加控制回路失败");
                }
                return ApiResult<LoopDto>.Ok(mapper.Map<LoopDto>(entity));
            }
            catch (Exception e)
            {
                return ApiResult<LoopDto>.Fail($"添加控制回路错误, {e.Message}");
            }
        }

        /// <summary>
        /// 修改控制回路内容
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        public async Task<ApiResult<LoopDto>> UpdateLoopAsync(LoopTable table)
        {
            try
            {
                var counter = await CountAsync(a => a.Name == table.Name && a.Id != table.Id);
                if (counter > 0)
                {
                    return ApiResult<LoopDto>.Fail($"存在同名的控制回路(Name: {table.Name})");
                }

                counter = await _dbContext.Equip.CountAsync(a => a.Id == table.equipId);
                if (counter == 0)
                {
                    return ApiResult<LoopDto>.Fail("控制回路所属设备不存在");
                }
                var pv = await _dbContext.Vars.FirstOrDefaultAsync(a => a.Name == table.PVName);
                if (pv == null)
                {
                    return ApiResult<LoopDto>.Fail($"过程值变量不存在(PVName: {table.PVName})");
                }
                if (pv.DataType == Entities.Extensions.DataTypeEnum.BOOLEAN ||
                    pv.DataType == Entities.Extensions.DataTypeEnum.STRING)
                {
                    return ApiResult<LoopDto>.Fail($"过程值变量类型不正确(PVName: {table.PVName})");
                }

                var sv = await _dbContext.Vars.FirstOrDefaultAsync(a => a.Name == table.SVName);
                if (sv == null)
                {
                    return ApiResult<LoopDto>.Fail($"设定值变量不存在(SVName: {table.SVName})");
                }
                if (sv.DataType == Entities.Extensions.DataTypeEnum.BOOLEAN ||
                    sv.DataType == Entities.Extensions.DataTypeEnum.STRING)
                {
                    return ApiResult<LoopDto>.Fail($"设定值变量类型不正确(SVName: {table.SVName})");
                }
                if (sv.ReadOnly)
                {
                    return ApiResult<LoopDto>.Fail($"设定值变量是只读的(SVName: {table.SVName})");
                }

                var op = await _dbContext.Vars.FirstOrDefaultAsync(a => a.Name == table.OPName);
                if (op == null)
                {
                    return ApiResult<LoopDto>.Fail($"输出值变量不存在(OPName: {table.OPName})");
                }
                if (op.DataType == Entities.Extensions.DataTypeEnum.BOOLEAN ||
                    op.DataType == Entities.Extensions.DataTypeEnum.STRING)
                {
                    return ApiResult<LoopDto>.Fail($"输出值变量类型不正确(OPName: {table.OPName})");
                }
                if (op.ReadOnly)
                {
                    return ApiResult<LoopDto>.Fail($"输出值变量是只读的(OPName: {table.OPName})");
                }

                table.Equip = _dbContext.Equip.FirstOrDefault(a => a.Id == table.equipId);

                var entity = await UpdateAsync(table);
                if (entity == null)
                {
                    return ApiResult<LoopDto>.Fail("更改控制回路失败");
                }
                return ApiResult<LoopDto>.Ok(mapper.Map<LoopDto>(entity));
            }
            catch (Exception e)
            {
                return ApiResult<LoopDto>.Fail($"更改控制回路错误, {e.Message}");
            }
        }

        /// <summary>
        /// 删除控制回路
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ApiResult<LoopDto>> DeleteLoopAsync(int id)
        {
            try
            {
                var entity = _dbContext.Loop.FirstOrDefault(x => x.Id == id);
                if (entity == null)
                {
                    return ApiResult<LoopDto>.Fail($"没有发现ID号为{id}的控制回路");
                }

                await DeleteAsync(entity);

                var dto = mapper.Map<LoopDto>(entity);
                return ApiResult<LoopDto>.Ok(dto);
            }
            catch (Exception e)
            {
                return ApiResult<LoopDto>.Fail($"删除控制回路错误, {e.Message}");
            }
        }
    }
}
